// import { Session, pomelo } from "pomelo2-creator";
import EventBase from "../eventBase";
import RankingList from "../prefab/rankingList";
import { eHotUpdateEvent } from "../update/HotUpdateEvent";
import { Game_Const } from "../update/ManifestInfo";
import DataMgr from "./dataManager";
import ServerMgr from "./serverManager";




export const g_rankType = {
    'coin': 'coin',
    'block': 'block',
    'snake': 'snake'
}


export default class NetMgr extends EventBase {
    private static instance: NetMgr;
    // pomelo:Session
    appid: string = 'wx_block'
    unnionid: string = '123434234';
    servo: httpFunc.request = null;
    headers = {
        authentication: ''
    }
    public static Ins() {
        if (!this.instance) {
            this.instance = new NetMgr();
            this.instance.servo = new httpFunc.request('http://118.31.115.133:8086', {});
        }
        return this.instance;


    }


    post(url: string, data: any) {
        // return NetMgr.Ins().servo.post(url,data,true);

        return ServerMgr.Ins().post(url, data);

    }


    getSubGameConfig() {
        let xhr = new XMLHttpRequest();
        xhr.onreadystatechange = () => {
            if (xhr.readyState == 4 && xhr.status >= 200 && xhr.status < 400) {
                let response = xhr.responseText;

                const subGameInfo = (JSON.parse(response));


                for (let i in DataMgr.Ins().subGameInfo) {
                    const info = DataMgr.Ins().subGameInfo[i];
                    const name = info.name;
                    for (let s in subGameInfo) {
                        const sInfo = subGameInfo[s];
                        if (name == sInfo.name) {
                            DataMgr.Ins().subGameInfo[i].packageUrl = sInfo.packageUrl;
                        }
                    }
                }


                cc.systemEvent.emit(eHotUpdateEvent.subGameGetConfigResult, DataMgr.Ins().subGameInfo);
            }
        };
        xhr.open("GET", `${Game_Const.server_ip}/subGameConfig.json`, true);
        xhr.send();
    }


    async getRankList(type) {
        const rankInfo = await this.servo.get(`/records/ranking/top?ranking=${type}`);
        if (rankInfo.status === 200) {
            const info = rankInfo.body.data;
            console.log('info = ', info);


            return { data: info.tops, user: { rank: info.self.index, score: info.self.score } };
        }

    }

    async postRankList(type, score) {
        //         post http://domain:8086/records/ranking
        //  *     { ranking: 'xxx', score: 'xxx' }
        //  *  => { status:'ok' }
        const rankInfo = await this.servo.post(`/records/ranking`, { ranking: type, score: score }, true);
        if (rankInfo.status === 200) {
            const info = rankInfo.body;
            console.log('info = ', info);
        }


    }

}




// @ts-ignore
// const Promise = require('promise-polyfill');

export interface QueryOption {
    uri?: string,
    url?: string,
    method?: string,
    query?: object;
    headers?: object;
    body?: object;
    timeout?: number;
    json?: boolean;
    withCredentials?: boolean;
}


function uploadServerMsgTimeUse(startTime: number, key: string, type: number = 0) {
    const endTime = Date.now();
    const time = endTime - startTime
    const types = ['websocket', 'http'];
    cc.log(`---------${types[type]}  msg :: ${key}  use time:::${time}`);
}
function request_promise(opts: QueryOption): Promise<any> {
    const timeStart = Date.now();
    return new Promise((resolve, reject) => {
        const req = new XMLHttpRequest();
        req.timeout = opts.timeout || 15000;
        if (!cc.sys.isNative) {
            req.withCredentials = opts.withCredentials || false;
        }

        const timeOut = setTimeout(() => {
            cc.log('http time out!!!!!!!!!!!!!!');
            uploadServerMsgTimeUse(timeStart, opts.uri, 1);
            resolve({ status: 500, headers: req.getAllResponseHeaders(), body: { code: 500 } });
        }, req.timeout || 15000);


        cc.log('http+ = ' + JSON.stringify(opts));

        req.onreadystatechange = function () {
            if (req.readyState === 4) {
                cc.log('http get responce!!!!!!!!');
                clearTimeout(timeOut);
                if (req.status >= 200 && req.status < 300) {
                    try {
                        uploadServerMsgTimeUse(timeStart, opts.uri, 1);
                        resolve({ status: req.status, headers: req.getAllResponseHeaders(), body: JSON.parse(req.responseText) });
                    } catch (_) {
                        uploadServerMsgTimeUse(timeStart, opts.uri, 1);
                        resolve({ status: req.status, headers: req.getAllResponseHeaders(), body: req.responseText });
                    }
                } else if (req.status > 0) {
                    uploadServerMsgTimeUse(timeStart, opts.uri, 1);
                    resolve({ status: req.status, headers: req.getAllResponseHeaders() });
                }
            }
        };

        req.onerror = reject;

        req.open(opts.method || 'GET', opts.uri || opts.url, true);

        if (opts.headers) {
            for (let i in opts.headers) {
                req.setRequestHeader(i, opts.headers[i]);
            }
        }

        if (opts.body) {
            if (opts.json) {
                req.setRequestHeader('Content-Type', 'application/json; charset=UTF-8');
            }
            req.send(typeof opts.body === 'object' ? JSON.stringify(opts.body) : opts.body);
            return;
        }
        req.send();
    });
};

export namespace httpFunc {
    export class request {
        readonly domain: string;
        readonly headers: object | undefined;
        constructor(uri: string, headers?: object) {
            this.domain = uri;
            this.headers = headers;
        }

        async get(url: string, body?: object, json?: boolean): Promise<{ status: number, body: any, headers: object } | undefined> {

            return await request_promise({ method: 'GET', uri: `${this.domain}${url}`, headers: NetMgr.Ins().headers, query: body, json }).catch(e => {
                cc.error('http+getError = ' + JSON.stringify(e));
            });
        }

        async post(url: string, body?: object, json?: boolean): Promise<{ status: number, body: any, headers: object } | undefined> {
            return await request_promise({ method: 'POST', uri: `${this.domain}${url}`, headers: NetMgr.Ins().headers, body, json }).catch(e => {
                cc.error('http+postError = ' + JSON.stringify(e));
            });
        }
    }

    export function get(uri: string | QueryOption, cb?: { (readon: any): PromiseLike<any> }): Promise<{ status: number, body: any, headers: object } | undefined> {
        if (cb) {
            request_promise(typeof uri === 'object' ? uri : { uri, method: 'GET' }).then(cb.bind(null, null)).catch(cb);
        } else {
            return request_promise(typeof uri === 'object' ? uri : { uri, method: 'GET' });
        }
    }

    export function post(uri: QueryOption, cb?: { (readon: any): PromiseLike<any> }): Promise<{ status: number, body: any, headers: object } | undefined> {
        uri.method = 'POST';
        if (cb) {
            request_promise(uri).then(cb.bind(null, null)).catch(cb);
        } else {
            return request_promise(uri);
        }
    }
}

